#include "StdAfx.h"
#include "SupportiveFunctions.h"

void ApplySobel(IplImage * src, IplImage * dest);

const char* SupportiveFunctions::CenterMarkerFile = "CenterMarker.jpg";
const char* SupportiveFunctions::LeftMarkerFile = "LeftMarker.jpg";
const char* SupportiveFunctions::RightMarkerFile = "RightMarker.jpg";
const char* SupportiveFunctions::StethMarkerFile = "StethMarker.jpg";

SupportiveFunctions::SupportiveFunctions(void)
{
}

SupportiveFunctions::~SupportiveFunctions(void)
{
}

bool SupportiveFunctions::WithinRegion(IplImage* image, IplImage* templateImage, CvPoint point)
{
	if ((point.x > templateImage->width / 2 && point.x < image->width - templateImage->width / 2)
		&& (point.y > templateImage->height / 2 && point.y < image->height - templateImage->height / 2))
	{
		return true;
	}
	return false;
}

int SupportiveFunctions::GetLocationScore(int locationX, int referenceLocationX)
{
	//here we assume the initial frame to be 320 * 240 pixels wide
	int score = -((10 / (float)referenceLocationX) * locationX  - 10) * ((10 / (float)referenceLocationX) * locationX  - 10) + 100;
	return score;
}


CvPoint SupportiveFunctions::GetMatchWithMarker(IplImage* source, IplImage* templateSource, int & value)
{
	IplImage* processedImage = cvCloneImage(source);
	IplImage* templateImage = cvCloneImage(templateSource);

	ApplySobel(processedImage, processedImage);
	ApplySobel(templateImage, templateImage);

	IplImage * sourceWithBorder = cvCreateImage(cvSize(processedImage->width + templateImage->width, 
	processedImage->height + templateImage->height),
	IPL_DEPTH_8U, 
	1);
	cvCopyMakeBorder(processedImage, sourceWithBorder, cvPoint(templateImage->width / 2, templateImage->height / 2), IPL_BORDER_CONSTANT);

	int resultWidth = sourceWithBorder->width - templateImage->width + 1;
	int resultHeight = sourceWithBorder->height - templateImage->height + 1;
	IplImage * resultImage = cvCreateImage( cvSize(resultWidth, resultHeight), 32, 1 );
	cvMatchTemplate(sourceWithBorder, templateImage, resultImage, 1);
	double minVal, maxVal;
	CvPoint minLoc, maxLoc;
	IplImage* cloneImage = cvCloneImage(resultImage);
	cvMinMaxLoc(cloneImage, &minVal, &maxVal, &minLoc, &maxLoc, 0);

	cvReleaseImage(&cloneImage);
	cvReleaseImage(&resultImage);
	cvReleaseImage(&sourceWithBorder);
	cvReleaseImage(&processedImage);
	cvReleaseImage(&templateImage);
	
	value = minVal;
	return minLoc;
}

CvPoint SupportiveFunctions::GetMatchWithMarker(IplImage* source, IplImage* templateSource)
{
	int minimumValue = 0;
	return GetMatchWithMarker(source, templateSource, minimumValue);
}

IplImage* SupportiveFunctions::GetCroppedImage(IplImage * source, CvRect rect)
{
	cvSetImageROI(source, rect);
	IplImage * croppedImage = cvCreateImage(cvGetSize(source), 8, 1);
	cvCopy(source, croppedImage);
	cvResetImageROI(source);
	return croppedImage;
}

void SupportiveFunctions::SaveImageRegion(IplImage * source, CvRect rect, const char * fileName)
{
	IplImage * croppedImage = GetCroppedImage(source, rect);
	cvSaveImage(fileName, croppedImage);
	cvReleaseImage(&croppedImage);
}
int SupportiveFunctions::GetDifference(IplImage * imageBig, IplImage * imageSmall, CvPoint pointToPlace)
{
	IplImage* bigImage = cvCloneImage(imageBig);
	IplImage* smallImage = cvCloneImage(imageSmall);

	ApplySobel(bigImage, bigImage);
	cvThreshold(bigImage, bigImage, 128, 255, CV_THRESH_OTSU);

	ApplySobel(smallImage, smallImage);
	IplImage* paddedSmallImage = PasteImage(bigImage, smallImage, pointToPlace);
	cvThreshold(paddedSmallImage, paddedSmallImage, 128, 255, CV_THRESH_OTSU);
	cvAbsDiff(bigImage, paddedSmallImage, paddedSmallImage);
	int differenceCount = cvCountNonZero(paddedSmallImage);

	cvReleaseImage(&paddedSmallImage);
	cvReleaseImage(&smallImage);
	cvReleaseImage(&bigImage);

	return differenceCount;
}


IplImage * SupportiveFunctions::SetZeroToRegion(IplImage *source, CvRect rect)
{
	IplImage * clone = cvCloneImage(source);
	SetZeroOnRegion(clone, rect);
	return clone;
}

void SupportiveFunctions::SetZeroOnRegion(IplImage *source, CvRect rect)
{
	if ((rect.x > 0 && rect.y > 0)
		&& (rect.width < source->width - rect.x && rect.height < source->height - rect.y))
	{
		cvSetImageROI(source, rect);
		cvSetZero(source);
		cvResetImageROI(source);
	}
}

IplImage * SupportiveFunctions::PasteImage(IplImage * PastingImage, IplImage * pastedImage, CvPoint pointToPlace)
{
	IplImage* paddedImage = cvCreateImage(cvGetSize(PastingImage), 8, 1);
	cvSetZero(paddedImage);
	cvSetImageROI(paddedImage, cvRect(pointToPlace.x - pastedImage->width / 2, pointToPlace.y - pastedImage->height / 2, pastedImage->width, pastedImage->height));
	cvCopy(pastedImage, paddedImage);
	cvResetImageROI(paddedImage);

	return paddedImage;
}

void SupportiveFunctions::ApplySobel(IplImage * src, IplImage * dest)
{
	IplImage* one = cvCloneImage(src);
	IplImage* two = cvCloneImage(src);

	cvSobel(src, one, 2, 0);
	cvSobel(src, two, 0, 2 );

	cvAdd(one, two, dest);
	cvReleaseImage( &one );
	cvReleaseImage( &two );
}
